import router from '@/bank/router'
import constantRoutes from '@/bank/router/constantRoutes'
import commonRoutes from '@/bank/router/commonRoutes'
import asyncRoutes from '@/bank/router/asyncRoutes'

export const hasPermission = (route, user) => {
  if (route.meta) {
    const { job, org, regionLevel, excludeJob, scopes, authExecutor } = route.meta
    const { job: userJob, clientOrgClass: userOrg, orgRegionLever, scopeArr } = user

    // 路由权限自定义处理逻辑
    if (authExecutor) {
      return authExecutor(user)
    }

    // 权限判断， 系统后台配置权限
    if (scopes && !scopeArr.some(val => scopes.includes(val))) {
      return false
    }

    const excludeJobValid = excludeJob && excludeJob.includes(userJob)
    if (excludeJobValid) {
      return false
    }
    const jobAndOrgValid = (!job || job.includes(userJob)) && (!org || org.includes(userOrg))
    const regionLevelValid =
      !regionLevel ||
      (Array.isArray(regionLevel)
        ? regionLevel.includes(+orgRegionLever)
        : +orgRegionLever === regionLevel)
    return jobAndOrgValid && regionLevelValid
  } else {
    return true
  }
}

// 递归过滤异步路由表，返回符合用户角色权限的路由表
const filterAsyncRouter = (routes, user) => {
  const res = []

  routes.forEach(route => {
    const tmp = { ...route }

    if (hasPermission(route, user)) {
      if (tmp.children) {
        tmp.children = filterAsyncRouter(tmp.children, user)
      }
      res.push(tmp)
    }
  })

  return res
}

// 无 '/' 根路由，需要添加并重定向到第一个路由
const addRootRoute = routes => {
  if (routes.some(item => item.path === '/') || !routes.length) {
    return routes
  }
  routes.unshift({
    path: '/',
    redirect: routes[0].path,
  })
  return routes
}

const addCommonRoute = routes => {
  return new Promise((resolve, reject) => {
    if (!routes || !routes.length) {
      return reject(router)
    }

    let child = []
    for (const route of routes) {
      if (route.children) {
        child = route
        break
      }
    }

    // 异步路由不存在（可能是由于已登录，但没有权限）
    if (!child.children) {
      return reject(router)
    }
    for (const r of child.children) {
      if (r.children) {
        r.children.push.apply(r.children, commonRoutes)
        break
      }
    }

    resolve(routes)
  })
}

const state = {
  routes: constantRoutes,
  asyncRoutes: [],
}
const getters = {
  routes: state => state.routes,
  asyncRoutes: state => state.asyncRoutes,
}
const actions = {
  generateRoutes({ commit }, userData) {
    return new Promise((resolve, reject) => {
      let accessedRouters = filterAsyncRouter(asyncRoutes, userData)
      accessedRouters = addRootRoute(accessedRouters)
      addCommonRoute(accessedRouters)
        .then(res => {
          accessedRouters = [...res]
          commit('setRoutes', accessedRouters)
          accessedRouters.forEach(r => router.addRoute(r))
          resolve()
        })
        .catch(err => {
          reject(err)
        })
    })
  },
}
const mutations = {
  setRoutes: (state, payload) => {
    state.asyncRoutes = payload
    state.routes = constantRoutes.concat(payload)
  },
}

export default {
  state,
  getters,
  actions,
  mutations,
}
